package com.graspyun.plugin.tverify

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.URLSpan
import android.view.WindowManager
import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.TextView
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.rich.oauth.callback.CertificaioinCallback
import com.rich.oauth.callback.InitCallback
import com.rich.oauth.callback.PreLoginCallback
import com.rich.oauth.callback.TokenCallback
import com.rich.oauth.core.RichAuth
import com.rich.oauth.core.UIConfigBuild
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import org.json.JSONObject
import java.util.HashMap
import kotlin.collections.set

/** TverifyPlugin */
class TverifyPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    private lateinit var channel: MethodChannel
    private lateinit var context: Context
    private lateinit var activity: Activity

    private var result: Result? = null
    private var checked: Boolean = false

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        context = flutterPluginBinding.applicationContext
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "tverify")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        this.result = result
        val arguments = call.arguments as Map<*, *>? ?: HashMap<Any?, Any?>()
        val instance = RichAuth.getInstance()
        when (call.method) {
            "initLogin" -> initLogin(arguments)
            "preLogin" -> preLogin()
            "login" -> login(arguments)
            "deleteScrip" -> deleteScrip()
            "setTimeout" -> setTimeout(arguments)
            "dismissLogin" -> dismissLogin()
            "getNetworkType" -> result.success(instance.getNetworkType(context))
            "getOperatorType" -> result.success(instance.getOperatorType(context))
            "certificationNumber" -> certificationNumber(arguments)
            "setDebugModel" -> instance.setDebugMode(arguments["isDebug"] as Boolean)
            "setLoginBtn" -> instance.setLoginBtn(arguments["text"] as String)
            "setSecondPrivacyCallback" -> {
                instance.setSecondPrivacyCallback(arguments["isCallback"] as Boolean)
            }

            else -> result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        result = null
        channel.setMethodCallHandler(null)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    }

    override fun onDetachedFromActivity() {
    }

    private fun initLogin(arguments: Map<*, *>) {
        val appId = arguments["appId"] as String
        RichAuth.getInstance().init(context, appId, object : InitCallback {
            override fun onInitSuccess() {
                result?.success(null)
            }

            override fun onInitFailure(errorMsg: String) {
                val jsonObject = JSONObject(errorMsg)
                val code = jsonObject["code"] as Int
                val message = jsonObject["msg"] as String
                result?.error(code.toString(), message, errorMsg)
            }
        })
    }

    private fun preLogin() {
        RichAuth.getInstance().preLogin(activity, object : PreLoginCallback {
            override fun onPreLoginSuccess() {
                result?.success(null)
            }

            override fun onPreLoginFailure(errorMsg: String) {
                val jsonObject = JSONObject(errorMsg)
                val code = jsonObject["code"] as Int
                val message = jsonObject["msg"] as String
                result?.error(code.toString(), message, errorMsg)
            }
        })
    }

    private fun login(arguments: Map<*, *>) {
        val config = createUIConfigBuild(context, channel, arguments)
        this.checked = config.isProtocolSeleted
        val callback = object : TokenCallback {
            override fun onTokenSuccessResult(token: String?, carrier: String?) {
                result?.success(mapOf("token" to token, "carrier" to carrier))
            }

            override fun onTokenFailureResult(errorMsg: String) {
                val jsonObject = JSONObject(errorMsg)
                val code = jsonObject["code"] as Int
                val message = jsonObject["msg"] as String
                result?.error(code.toString(), message, errorMsg)
            }

            override fun onCheckboxChecked(context: Context, jsonObject: JSONObject?) {
                channel.invokeMethod("onCheckboxChecked", jsonObject?.run {
                    val map = mutableMapOf<String, Any>()
                    for (key in keys()) {
                        map[key] = get(key)
                    }
                    return@run map
                })
            }

            override fun onLoginClickComplete(context: Context, jsonObject: JSONObject?) {
                channel.invokeMethod("onLoginClickComplete", jsonObject?.run {
                    val map = mutableMapOf<String, Any>()
                    for (key in keys()) {
                        map[key] = get(key)
                    }
                    return@run map
                })
            }

            override fun onLoginClickStart(context: Context, jsonObject: JSONObject?) {
                channel.invokeMethod("onLoginClickStart", jsonObject?.run {
                    val map = mutableMapOf<String, Any>()
                    for (key in keys()) {
                        map[key] = get(key)
                    }
                    return@run map
                })
            }

            override fun onCheckboxCheckedChange(checked: Boolean) {
                this@TverifyPlugin.checked = checked
                channel.invokeMethod("onCheckboxCheckedChange", checked)
            }

            override fun onAuthLoginListener(context: Context) {
                channel.invokeMethod("onAuthLoginListener", null)
                if (checked) {
                    RichAuth.getInstance().setSecondPrivacyCallback(true)
                } else {
                    PrivacyDialog(context, config).show()
                }
            }

            override fun onPressBackListener(context: Context) {
                channel.invokeMethod("onPressBackListener", null)
            }
        }
        RichAuth.getInstance().login(activity, callback, config)
    }

    private fun deleteScrip() {
        RichAuth.getInstance().delscrip(context)
        result?.success(true)
    }

    private fun setTimeout(arguments: Map<*, *>) {
        RichAuth.getInstance().setOverTime(((arguments["duration"] as Double)).toInt())
        result?.success(null)
    }

    private fun dismissLogin() {
        RichAuth.getInstance().closeOauthPage()
        result?.success(null)
    }

    private fun certificationNumber(arguments: Map<*, *>) {
        val number = arguments["number"] as String
        RichAuth.getInstance().certificationNumber(context, number, object : CertificaioinCallback {
            override fun onPhoneNumberCertificationSuccess(p0: String?) {
                result?.success(p0)
            }

            override fun onPhoneNumberCertificationFailure(p0: String?) {
                result?.error("phone_number_certification_failure", p0, null)
            }
        })
    }
}

private class PrivacyDialog(context: Context, private val config: UIConfigBuild) :
    BottomSheetDialog(context, R.style.BottomSheetTheme) {
    private val tvContent: TextView
        get() = findViewById(R.id.tv_content)!!
    private val btnAgreement: Button
        get() = findViewById(R.id.btn_agreement)!!
    private val ibClose: ImageButton
        get() = findViewById(R.id.ib_close)!!

    init {
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
        behavior.isHideable = false
        behavior.isDraggable = false
        setOnCancelListener {
            RichAuth.getInstance().setSecondPrivacyCallback(false)
        }
    }

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.dialog_privacy)

        window?.setLayout(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT
        )

        val rootView = findViewById<FrameLayout>(R.id.root_view)!!
        ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, windowInsets ->
            val systemBars = WindowInsetsCompat.Type.systemBars()
            val insets = windowInsets.getInsets(systemBars)
            rootView.setPadding(insets.left, 0, insets.right, insets.bottom)
            val newInsets = Insets.of(0, insets.top, 0, 0)
            WindowInsetsCompat.Builder(windowInsets).setInsets(systemBars, newInsets).build()
        }

        ibClose.setImageBitmap(
            loadAsset(
                context,
                "assets/images/3.0x/close.png",
                "tverify"
            )
        )
        ibClose.setOnClickListener {
            RichAuth.getInstance().setSecondPrivacyCallback(false)
            dismiss()
        }
        val loginBtnBg = config.loginBtnBg
        btnAgreement.setBackgroundResource(loginBtnBg)
        btnAgreement.setOnClickListener {
            RichAuth.getInstance().setSecondPrivacyCallback(true)
            dismiss()
        }
        tvContent.movementMethod = LinkMovementMethod.getInstance()
        val carrierName = when (RichAuth.getInstance().getOperatorType(context).toInt()) {
            1 -> "移动"
            2 -> "联通"
            3 -> "电信天翼"
            else -> ""
        }
        val protocols = mapOf<String?, String?>(
            config.protocolName to config.protocolUrl,
            config.secondProtocolName to config.secondProtocolUrl,
            config.thirdProtocolName to config.thirdProtocolUrl,
        ).filterNot { it.key.isNullOrEmpty() }.mapKeys { it.key!! }
        val builder = SpannableStringBuilder("已阅读并同意")
        var index = 0
        protocols.forEach {
            if (index > 0) {
                builder.append("、")
            }
            index++
            builder.append("《${it.key}》", LinkSpan(it.value, config.privacyColor), Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
        }
        if (protocols.isNotEmpty()) {
            builder.append("和")
        }
        builder.append("《中国${carrierName}认证服务协议》")
        tvContent.text = builder
    }
}

private class LinkSpan(url: String?, val color: Number) : URLSpan(url) {
    override fun updateDrawState(ds: TextPaint) {
        ds.color = color.toInt()
        ds.isUnderlineText = false
    }
}
